<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div id='tt'></div>
</body>
<script>
    // 01 Default Parameters（默认参数）
    /*let func = function(h= 10,w= 10){
        console.log("h:"+ h,"w:"+w)
    }
    func(20,20)
    func()*/

    //Multi-line Strings （多行字符串）
    /*var fourAgreements = 'You have the right to be you\n'
        +' You can only be you when you do your best.';
    console.log(fourAgreements)*/
    //es6
    /*var strings_d = `You have the right to be you
        You can only be you when you do your best.`;
    console.log(strings_d)*/
    //var first = 'li',
    //    last = 'xx';

    //var testHtml = `<div>
    //                    <ul>
    //                        <li>${first}</li>
    //                        <li>2</li>
    //                        <li>3</li>
    //                    </ul>
    //                </div>`;
    //console.log(testHtml)
//    document.getElementById("tt").innerHTML = testHtml;
//    document.getElementsByTagName('body')[0].innerHTML = testHtml;
    //document.querySelector('body').innerHTML = testHtml;

    //Template Literals（模板对象）
    //处理字符串与变量的拼接问题
    //var name = 'Your name is ' + first + ' ' + last + '.';
    //console.log(name)
    //es6
    //要注意的是：用的是反引号
    //var name6 = `Your name is ${first} ${last}.`;
    //console.log(name6)

    //块级作用域
    //ES6提出了两个新的声明变量的命令：let和const。其中，let完全可以取代var，因为两者语义相同，而且let没有副作用。
    //(1).使用let 取代 var

    //1.for循环的计数器，就很合适使用let命令。
    /*  let */
    //for (let i = 0; i < 10; i++) {}
    //console.log(i);   //ReferenceError: i is not defined

    /* var */
    //for (var i = 0; i < 10; i++) {}
    //console.log(i);   // 10
    //2.var命令存在变量提升效用，let命令没有这个问题。提倡先声明后使用

    //解构赋值
    //const arr = [1,2,3,4];
//    const [one, two, ...three] = arr;
//    console.log(one)
//    console.log(two)
//    console.log(three)

    //使用扩张运算符得到的新数组 与原数组 比较 等于与全等都是false
    //const newArr = [...arr];

    //而直接赋值整个数组那么等于和全等都是true
    //const newArr = arr;

    //console.log(arr[0] === newArr[0])
    //console.log(arr === newArr)
    //console.log(arr == newArr)
    //console.log(newArr)



    //js== 与 === 的区别
        //1、对于string,number等基础类型，==和===是有区别的
        //.log('1' == 1)
        //console.log('1' === 1)
        //1）不同类型间比较，==之比较“转化成同一类型后的值”看“值”是否相等，===如果类型不同，其结果就是不等

        //2）同类型比较，直接进行“值”比较，两者结果一样
        //2、对于Array,Object等高级类型，==和===是没有区别的进行“指针地址”比较
        //console.log(arr === newArr)
        //console.log(arr == newArr)

        //3、基础类型与高级类型，==和===是有区别的
        //1）对于==，将高级转化为基础类型，进行“值”比较
        //2）因为类型不同，===结果为false

     // 总结：
        //‘==’ 不同类型之间的比较回先进行类型转换，然后在比较值。如果类型相同则直接比较值;
        //所以同类型之间的比较‘==’与‘===’没有区别;


    //let 与 var const

    //块级作用域：
        //一对花括号里面的代码就构成一个块级作用域
        //块与块之间可以使用同样的变量名称
    //function calculateTotalAmount(vip){
    //    let amount  = 0; // probably should also be let, but you can mix var and let
    //    if (vip) {
    //        let amount = 1; // first amount is still 0 
    //        console.log(amount)
    //    }
    //        { // more crazy blocks!  
    //            let amount = 100; // first amount is still 0 
    //            console.log(amount)
    //        {  
    //            let amount = 1000; // first amount is still 0  
    //            console.log(amount)
    //        }  
    //    }    
    //    return amount;  
    //} 
    //console.log(calculateTotalAmount(true));  //0 因为块作用域中有了let。
//
//
    //var n = 1;
    //var n = 2;
    //var n = 3;
    //console.log(n)
//
    //let m = 1;
    //// let m = 2;
    //// let m = 3;
    //console.log(m);
    // let 与 var 的区别：
        //var 多次声明同一个变量，后面的会覆盖前面的;
        //let 只允许同一个变量声明一次，多次声明会报错


    //Classes （类）
    //class baseModel {  
    //    constructor(options, data) {// class constructor， 注意我们对options 和data使用了默认参数值。
    //        this.name = 'Base';  
    //        this.url = 'http://azat.co/api';  
    //        this.data = data;  
    //        this.options = options;  
    //    }  
    //    getName() { // class method  
    //        console.log(`Class name: ${this.name}`);  
    //    } 
    //    getUrl() { // class method  
    //         console.log(`Url: ${this.url}`);  
    //    }
    //}
//
    ////AccountModel 从类baseModel 中继承而来:
    //class AccountModel extends baseModel {
    //    constructor(options, data) {
    //        super({private: true}, ['32', '5242']); 
    //        this.url +='/accounts/';  
    //    }
    //    get accountsData() {
    //        return this.data;  
    //    }  
    //} 
//
    //let accounts = new AccountModel(5);
    //accounts.getName();
    //accounts.getUrl();
    //console.log(`Data is ${accounts.accountsData}` ); 

    //Modules （模块）的导入/导出
    //ES5：
        //导出：
        //module.exports = { port: 3000, getAccounts: function() { ... }}
        //导入：
        //var service = require('module.js');
        //console.log(service.port); // 3000
        //因为导出是整体导出，所以导入时只能导入整个js文件

    //ES6：
        //导出：
        //export var port = 3000;
        //export function getAccounts(url) { ...}
        //导入：我们需用import {name} from ‘my-module’语法
        //按需导入
        //import {port, getAccounts} from 'module';
        //console.log(port); // 300

        //整体导入
        //import * as service from 'module';
        //console.log(service.port); // 3000

    //Set  ES6提供了新的数据结构Set。类似于数组，只不过其成员值都是唯一的，没有重复的值。Set本身是一个构造函数，用来生成Set数据结构
     //let arr = [1,2,1,2,3,4,5,4,5];
     //console.log(arr)
     //let s = new Set(arr);
     //arr = Array.from(s);
     //console.log(arr)

     //let arr1 = [1,2,3,4,3,4,2,3];
     //function delEL(arr){
     //   return Array.from(new Set(arr))
     //}
     //arr1 = delEL(arr1);
     //console.log(arr1);

    //箭头函数
    //区别一：普通function函数和箭头函数的行为有一个微妙的区别，箭头函数没有它自己的this值，箭头函数内的this值继承自外围作用域。
    //ES5处理this的方法：
    {
        addAll: function addAll(pieces) {
            var self = this;
                _.each(pieces, function (piece) {
                    self.add(piece);
            });
        }
    }
        //在这里，你希望在内层函数里写的是this.add(piece)，不幸的是内层函数并未从外层函数继承this的值
        //在内层函数里，this会是window或undefined，临时变量self用来将外部的this值导入内部函数。
        //（另一种方式是在内部函数上执行.bind(this)，两种方法都不甚美观。）

    //ES6中，不需要再hackthis了，但你需要遵循以下规则：
    //1.通过object.method()语法调用的方法使用非箭头函数定义，这些函数需要从调用者的作用域中获取一个有意义的this值。
    //2.其它情况全都使用箭头函数。
    {
        addAll: function addAll(pieces) {
            _.each(pieces, piece => this.add(piece));
        }
    }
    //在ES6中你可以用更简洁的方式编写对象字面量中的方法
    {
        addAll(pieces){
            _.each(pieces, piece => this.add(piece));
        }
    }
    //区别二：箭头函数与非箭头函数间还有一个细微的区别，箭头函数不会获取它们自己的arguments对象。诚然，在ES6中，你可能更多地会使用不定参数和默认参数值这些新特性。


</script>
</html>